package com.example.service.impl;

import cn.dev33.satoken.session.SaTerminalInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.example.constant.BanTypeEnum;
import com.example.constant.EnumConstant;
import com.example.constant.RedisConstant;
import com.example.constant.UserType;
import com.example.exception.BusinessException;
import com.example.mapper.*;
import com.example.model.DTO.*;
import com.example.model.Result;
import com.example.model.UserProfile;
import com.example.model.pojo.*;
import com.example.model.vo.PersonVO;
import com.example.model.vo.ResultVO;
import com.example.model.vo.SocialSecurityBureauVO;
import com.example.model.vo.SponsorVO;
import com.example.service.UserService;
import com.example.utils.AliOSSUtils;
import com.example.utils.MaskingUtils;
import com.example.utils.PhoneValidator;
import com.example.utils.WeBASEUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.fisco.bcos.sdk.crypto.CryptoSuite;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.crypto.signature.ECDSASignatureResult;
import org.fisco.bcos.sdk.model.CryptoType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.example.constant.ContractConstant.*;
import static com.example.utils.SignUtils.generateSigantureWithSecp256k1;

/**
 * @author zhexueqi
 * @ClassName UserServiceImpl
 * @since 2024/4/11 21:07
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {



    @Value("${system.contract.owner:0x3138c3afbfcb3d870a06e07d88f8967e7d27b2eb}")
    String ownerAddress;
    @Autowired
    WeBASEUtils weBASEUtils;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private SponsorMapper sponsorMapper;
    @Autowired
    private SocialMapper socialMapper;
    @Resource
    private LoginLogMapper loginLogMapper;
    @Resource
    private OperationLogMapper operationLogMapper;
    @Autowired
    private AliOSSUtils aliOSSUtils;

    @Resource
    private RedisTemplate redisTemplate;

    @Override
    public Result<String> banUser(Long userId, LocalDateTime expiryTime, Integer banType) {
        Person user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException(ResultVO.PARAM_EMPTY);
        }
        BanTypeEnum banTypeEnum = BanTypeEnum.getByCode(banType);
        if (banTypeEnum == null) {
            throw new BusinessException(ResultVO.PARAM_ERROR);
        }
        user.setStatus(0);
        user.setBanExpiryTime(expiryTime);
        user.setBanType(banType);
        userMapper.updateById(user);
        StpUtil.disable(userId, banTypeEnum.getType(), expiryTime != null ? expiryTime.getSecond() : -1);
        return Result.success("封禁成功: " + banTypeEnum.getDesc());
    }

    @Override
    public Result<String> unbanUser(Long userId, Integer banType) {
        Person user = userMapper.selectById(userId);
        if (user == null) {
            return Result.error("用户不存在");
        }
        BanTypeEnum banTypeEnum = BanTypeEnum.getByCode(banType);
        if (banTypeEnum == null) {
            throw new BusinessException(ResultVO.PARAM_ERROR);
        }

        user.setStatus(1);
        user.setBanExpiryTime(null);
        userMapper.updateById(user);
        StpUtil.untieDisable(userId, "login");
        return Result.success("解封成功");
    }


    /**
     * 用户登录
     * 
     * @param userDTO 用户数据传输对象，包含用户地址、名称、签名安全信息和用户类型
     * @param request HTTP请求对象
     * @return Result 包含用户详细信息的结果对象
     * @throws BusinessException 如果用户数据有问题或用户不存在，抛出业务异常
     */
    @Override
    public Result<Object> login(UserDTO userDTO, HttpServletRequest request) {
        log.info("用户登录请求: 用户类型={}, 用户名={}", userDTO.getType(), userDTO.getName());

        try {
            // 校验基本参数
            validateLoginParams(userDTO);

            // 根据用户类型分发到不同的登录处理方法
            UserType userType;
            // 处理数字类型的用户类型
            Object userInfo;
            long userId = 0;
            switch (userDTO.getType()) {
                case "0":
                    userType = UserType.ADMIN;
                    break;
                case "1":
                    userType = UserType.EMPLOYEE;
                    break;
                case "2":
                    userType = UserType.SPONSOR;
                    break;
                case "3":
                    userType = UserType.BUREAU;
                    break;
                default:
                    // 尝试直接将字符串转换为枚举（兼容直接使用枚举名称的情况）
                    try {
                        userType = UserType.valueOf(userDTO.getType().toUpperCase());
                    } catch (IllegalArgumentException e) {
                        log.error("无效的用户类型: {}", userDTO.getType());
                        return Result.error(ResultVO.PARAM_ERROR);
                    }
            }
            PersonVO personVO;
            switch (userType) {
                case ADMIN:
                    personVO = adminLogin(userDTO);
                    userInfo = personVO;
                    userId = personVO.getId();
                    break;
                case EMPLOYEE:
                    personVO = employeeLogin(userDTO);
                    log.info("员工登录成功: {}", personVO.getName());
                    userInfo = personVO;
                    userId = personVO.getId();
                    break;

                case SPONSOR:
                    SponsorVO sponsorVO = sponsorLogin(userDTO);
                    log.info("企业登录成功: {}", sponsorVO.getSponsorName());
                    userInfo = sponsorVO;
                    userId = sponsorVO.getSponsorId();
                    break;
                case BUREAU:
                    SocialSecurityBureauVO bureauVO = bureauLogin(userDTO);
                    log.info("社保局登录成功: {}", bureauVO.getBureauCity());
                    userInfo = bureauVO;
                    userId = bureauVO.getBureauId();
                    break;
                default:
                    log.warn("未知的用户类型: {}", userType);
                    return Result.error(ResultVO.PARAM_ERROR);
            }
            // 检查封禁状态
            checkBanStatus(userId);
            // 写入访问令牌
            writeAccessToken(userId);
            // 记录登录日志
            writeLoginLog(userDTO, userId, request);
            return Result.success(userInfo);
        } catch (IllegalArgumentException e) {
            log.error("无效的用户类型: {}", userDTO.getType());
            return Result.error(ResultVO.PARAM_ERROR);
        } catch (BusinessException e) {
            log.error("登录失败: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("登录过程中发生未预期异常", e);
            throw new BusinessException(ResultVO.INTERNAL_ERROR);
        }

    }

    /**
     * 验证登录参数
     * 
     * @param userDTO 用户登录信息
     * @throws BusinessException 如果参数不完整则抛出异常
     */
    private void validateLoginParams(UserDTO userDTO) {
        if (StrUtil.isEmpty(userDTO.getUserAddress()) || StrUtil.isEmpty(userDTO.getName())
                || StrUtil.isEmpty(userDTO.getSignSecurity())
                || StrUtil.isEmpty(userDTO.getType())) {
            log.warn("登录参数不完整: address={}, name={}, type={}",
                    userDTO.getUserAddress(), userDTO.getName(), userDTO.getType());
            throw new BusinessException(ResultVO.PARAM_EMPTY);
        }
    }

    /**
     * 检查用户封禁状态，如果封禁已过期则自动解禁
     * 
     * @param userId 用户ID
     */
    private void checkBanStatus(Long userId) {
        Person user = userMapper.selectById(userId);
        if (user != null && user.getStatus() == 0
                && user.getBanExpiryTime() != null
                && LocalDateTime.now().isAfter(user.getBanExpiryTime())) {
            // 封禁已过期，自动解禁
            user.setStatus(1);
            user.setBanExpiryTime(null);
            userMapper.updateById(user);
            StpUtil.untieDisable(userId, "login");
            log.info("用户ID: {} 封禁已过期，自动解禁", userId);
        }
    }

    /**
     * 管理员登录
     */
    private PersonVO adminLogin(UserDTO userDTO) {
        if (!Objects.equals(userDTO.getUserAddress(), ownerAddress)) {
            log.warn("管理员登录失败: 非法地址");
            throw new BusinessException(ResultVO.ADDRESS_INVALID);
        }
        Person person = userMapper.getPersonByAddress(userDTO.getUserAddress());
        if(person ==null){
            log.error("管理员登录失败: 用户不存在");
            throw new BusinessException(ResultVO.USER_NOT_EXIST);
        }
        if (!StringUtils.equalsIgnoreCase(person.getSignSecurity(), userDTO.getSignSecurity())){
            throw new BusinessException(ResultVO.PASSWORD_ERROR);
        }
        log.info("管理员登录成功: {}", person.getName());
        PersonVO personVO = new PersonVO();
        BeanUtil.copyProperties(person, personVO);
        return personVO;
    }

    /**
     * 社保局用户登录处理
     * 
     * @param userDTO 用户登录信息
     * @return 社保局用户视图对象
     * @throws BusinessException 如果验证失败则抛出异常
     */
    private SocialSecurityBureauVO bureauLogin(UserDTO userDTO) {
        SocialSecurityBureau social = socialMapper.getSocialByAddress(userDTO.getUserAddress());
        if (social == null) {
            log.info("用户不存在");
            throw new BusinessException(ResultVO.ACCOUNTS_NOT_EXIST);
        }
        if (!social.getBureauAddress().equals(userDTO.getUserAddress())) {
            throw new BusinessException(ResultVO.ADDRESS_INVALID);
        }
        if (!social.getSignSecurity().equals(userDTO.getSignSecurity())) {
            throw new BusinessException(ResultVO.SIGN_INVALID);
        }
        if (!social.getBureauCity().equalsIgnoreCase(userDTO.getName())) {
            throw new BusinessException(ResultVO.NAME_ERROR);
        }
        SocialSecurityBureauVO socialVO = new SocialSecurityBureauVO();
        BeanUtil.copyProperties(social, socialVO);
        return socialVO;
    }

    /**
     * 为用户生成访问令牌
     * 
     * @param userId 用户ID
     */
    private void writeAccessToken(Long userId) {
        StpUtil.login(userId);
        StpUtil.getLoginId();
        StpUtil.getSession().set("userId", userId);
        List<SaTerminalInfo> terminalList = StpUtil.getTerminalListByLoginId(userId);
        for (SaTerminalInfo ter : terminalList) {
            System.out.println("登录index=" + ter.getIndex() + ", 设备type=" + ter.getDeviceType() + ", token="
                    + ter.getTokenValue() + ", 登录time=" + ter.getCreateTime());
        }
        log.info("用户登录成功，用户ID: {}", userId);
    }

    /**
     * 把用户登录信息写入登录日志中
     */
    private void writeLoginLog(UserDTO userDTO, Long userId, HttpServletRequest request) {
        List<SaTerminalInfo> terminalList = StpUtil.getTerminalListByLoginId(userId);
        for (SaTerminalInfo ter : terminalList) {
            System.out.println("登录index=" + ter.getIndex() + ", 设备type=" + ter.getDeviceType() + ", token="
                    + ter.getTokenValue() + ", 登录time=" + ter.getCreateTime());
            LoginLog loginLog = new LoginLog();
            loginLog.setUserAddress(userDTO.getUserAddress());
            loginLog.setUserType(Integer.valueOf(userDTO.getType()));
            // 时间戳转Date
            loginLog.setLoginTime(new Date(ter.getCreateTime()));
            loginLog.setLoginIp(request.getRemoteHost());
            loginLog.setLoginLocation(request.getRemoteHost());
            loginLog.setDeviceType(ter.getDeviceType());
//            loginLog.setBrowser(null);
//            loginLog.setOs(request.getHeader("User-Agent"));
            loginLog.setStatus(1);
            loginLog.setMsg("登录成功");
            loginLogMapper.insert(loginLog);
        }

    }

    /**
     * 员工用户登录处理
     * 
     * @param userDTO 用户登录信息
     * @return 员工用户视图对象
     * @throws BusinessException 如果验证失败则抛出异常
     */
    private PersonVO employeeLogin(UserDTO userDTO) {
        // 根据用户手机号查询用户信息
        Person person;
        person = userMapper.getPersonByAddress(userDTO.getUserAddress());
        // person = userMapper.getPersonByPhone(userDTO.getPhone());
        if (person == null) {
            log.info("用户不存在");
            throw new BusinessException(ResultVO.ACCOUNTS_NOT_EXIST);
        }
        // 验证用户名称是否匹配
        if (!person.getName().equals(userDTO.getName())) {
            throw new BusinessException(ResultVO.NAME_ERROR);
        }
        // 验证用户类型是否匹配
        if (person.getUserType() != Integer.parseInt(userDTO.getType())) {
            throw new BusinessException(ResultVO.USER_TYPE_ERROR);
        }
        // 验证签名是否有效
        if (!person.getSignSecurity().equals(userDTO.getSignSecurity())) {
            throw new BusinessException(ResultVO.SIGN_INVALID);
        }
        // 验证用户地址是否匹配 - 已注释掉，保留注释以便未来可能的需求变更
        // if (!person.getEmployeeAddress().equals(userDTO.getUserAddress())) {
        // throw new BusinessException(ResultVO.ADDRESS_INVALID);
        // }

        PersonVO personVO = new PersonVO();
        BeanUtil.copyProperties(person, personVO);

        return personVO;
    }

    /**
     * 企业用户登录处理
     * 
     * @param userDTO 用户登录信息
     * @return 企业用户视图对象
     * @throws BusinessException 如果验证失败则抛出异常
     */
    private SponsorVO sponsorLogin(UserDTO userDTO) {

        Sponsor sponsor = sponsorMapper.getSponsorByAddress(userDTO.getUserAddress());
        if (sponsor == null) {
            log.info("用户不存在");
            throw new BusinessException(ResultVO.ACCOUNTS_NOT_EXIST);
        }
        if (!sponsor.getSponsorName().equals(userDTO.getName())) {
            throw new BusinessException(ResultVO.NAME_ERROR);
        }
        if (!sponsor.getSignSecurity().equals(userDTO.getSignSecurity())) {
            throw new BusinessException(ResultVO.SIGN_INVALID);
        }
        if (!sponsor.getSponsorAddress().equals(userDTO.getUserAddress())) {
            throw new BusinessException(ResultVO.ADDRESS_INVALID);
        }
        SponsorVO sponsorVo = new SponsorVO();
        BeanUtil.copyProperties(sponsor, sponsorVo);
        return sponsorVo;
    }

    /**
     * 注册雇员账户
     * 将已注册的个人用户添加为企业员工，建立社保关系
     * 
     * @param insuranceAccountDTO 员工社保账户信息，包含地址、薪资和雇主地址
     * @return 注册结果，包含签名信息
     */
    @Override
    public Result<String> addEmployee(InsuranceAccountDTO insuranceAccountDTO) {
        // 参数校验
        if (StrUtil.isEmpty(insuranceAccountDTO.getAddress()) ||
                StrUtil.isEmpty(insuranceAccountDTO.getSponsorAddress()) ||
                insuranceAccountDTO.getSalary() <= 0) {
            log.error("注册员工参数不完整: {}", insuranceAccountDTO);
            return Result.error(ResultVO.PARAM_EMPTY);
        }

        // 验证用户是否存在
        Person existingPerson = userMapper.getPersonByAddress(insuranceAccountDTO.getAddress());
        if (existingPerson == null) {
            log.error("用户不存在，地址: {}", insuranceAccountDTO.getAddress());
            return Result.error(ResultVO.ACCOUNTS_NOT_EXIST);
        }

        // 验证雇主是否存在
        SponsorVO sponsor = sponsorMapper.getSponsorVOByAddress(insuranceAccountDTO.getSponsorAddress());
        if (sponsor == null) {
            log.error("雇主不存在，地址: {}", insuranceAccountDTO.getSponsorAddress());
            return Result.error(ResultVO.SPONSOR_NOT_EXIST);
        }

        try {
            // 准备合约调用参数
            List<Object> funcParam = new ArrayList<>();
            funcParam.add(insuranceAccountDTO.getAddress());
            funcParam.add(insuranceAccountDTO.getSalary());
            funcParam.add(insuranceAccountDTO.getSponsorAddress());

            // 生成签名
            CryptoSuite cryptoSuite = new CryptoSuite(CryptoType.ECDSA_TYPE);
            CryptoKeyPair cryptoKeyPair = cryptoSuite.getKeyPairFactory();
            ECDSASignatureResult ecdsaSignatureResult = generateSigantureWithSecp256k1(cryptoSuite, cryptoKeyPair,
                    insuranceAccountDTO.getAddress());
            String signStr = ecdsaSignatureResult.convertToString();

            // 调用智能合约
            String _result = weBASEUtils.funcPost(ownerAddress, ADD_EMPLOYEE, funcParam);
            JSONObject obj = JSONUtil.parseObj(_result);
            String statusOK = obj.get("message").toString();

            if (!statusOK.equals(EnumConstant.STATUS_OK)) {
                log.error("添加员工合约调用失败: {}", _result);
                return Result.error(ResultVO.CONTRACT_ERROR);
            }

            // 更新用户类型和签名
            userMapper.updateUser(EnumConstant.EMPLOYEE, insuranceAccountDTO.getAddress(), signStr);
            log.info("员工注册成功，地址: {}", insuranceAccountDTO.getAddress());

            return Result.success(signStr);
        } catch (Exception e) {
            log.error("添加员工过程中发生异常", e);
            return Result.error("添加员工过程中发生异常: " + e.getMessage());
        }
    }

    /**
     * 注册个人用户
     * 创建区块链账户并存储用户基本信息
     *
     * @param person 个人用户信息，包含姓名、身份证、年龄等基本信息
     * @return 注册结果，包含区块链地址和签名信息
     */
    @Override
    public Result<String> addPerson(Person person) {
        try {
            // 获取雇主信息和检查用户是否已存在
            SponsorVO sponsor = sponsorMapper.getSponsorByName(person.getEmployer());
            Person personByIdNumber = userMapper.getPersonByIdNumber(person.getIdNumber());
            JSONObject outputData = new JSONObject();

            // 数据校验
            Result<String> validationResult = validData(sponsor, personByIdNumber, person);
            if (validationResult.getCode() != 200) {
                log.warn("用户注册数据校验失败: {}, 错误码: {}", person.getName(), validationResult.getCode());
                return validationResult;
            }

            // 创建区块链账户
            CryptoSuite cryptoSuite = new CryptoSuite(CryptoType.ECDSA_TYPE);
            CryptoKeyPair cryptoKeyPair = cryptoSuite.getKeyPairFactory();
            String address = cryptoKeyPair.getAddress();
            log.info("为用户 {} 生成区块链地址: {}", person.getName(), address);

            // 再次检查用户是否已存在（防止并发注册）
            Person existingPerson = userMapper.getPersonByIdNumber(person.getIdNumber());
            if (existingPerson != null) {
                log.error("用户已存在，身份证号: {}", person.getIdNumber());
                return Result.error(ResultVO.ACCOUNT_EXIST);
            }

            // 生成签名
            List<Object> funcParam = new ArrayList<>();
            funcParam.add(address);
            ECDSASignatureResult ecdsaSignatureResult = generateSigantureWithSecp256k1(cryptoSuite, cryptoKeyPair,
                    address);
            String signStr = ecdsaSignatureResult.convertToString();

            // 调用智能合约
            String contractResult = weBASEUtils.funcPost(ownerAddress, ADD_PERSON, funcParam);
            JSONObject resultObj = JSONUtil.parseObj(contractResult);
            String statusOK = resultObj.get("message").toString();

            if (!statusOK.equals(EnumConstant.STATUS_OK)) {
                log.error("智能合约调用失败: {}", contractResult);
                return Result.error(ResultVO.CONTRACT_ERROR);
            }

            // 保存用户信息到数据库
            person.setSignSecurity(signStr);
            person.setEmployeeAddress(address);
            person.setUserType(0); // 设置初始用户类型为个人用户

            Integer insertResult = userMapper.addPerson(person);
            if (insertResult <= 0) {
                log.error("用户数据保存失败: {}", person.getName());
                return Result.error(ResultVO.DB_ERROR);
            }

            // 构建返回数据
            outputData.set("signSecurity", signStr);
            outputData.set("employeeAddress", address);
            outputData.set("name", person.getName());

            log.info("用户注册成功: {}, 地址: {}", person.getName(), address);
            return Result.success(outputData.toString());
        } catch (Exception e) {
            log.error("用户注册过程中发生异常", e);
            return Result.error("用户注册过程中发生异常: " + e.getMessage());
        }
    }

    public Result<String> validData(SponsorVO sponsor, Person personByIdNumber, Person person) {
        if (sponsor == null) {
            return Result.error(ResultVO.SPONSOR_NOT_EXIST);
        }
        if (personByIdNumber != null) {
            return Result.error(ResultVO.ACCOUNT_EXIST);
        }
        if (person.getIdNumber().length() != 18) {
            return Result.error(ResultVO.IDNUMBER_LENGTH_ERROR);
        }
        if (StrUtil.isBlank(person.getIdNumber())) {
            return Result.error(ResultVO.PARAM_EMPTY);
        }
        if (person.getAge() < 0) {
            return Result.error(ResultVO.AGE_ERROR);
        }
        if (person.getAge() > 120) {
            return Result.error(ResultVO.AGE_ERROR);
        }
        // if (personBo.getSalary()<0){
        // return Result.error(ResultVO.SALARY_ERROR);
        // }
        // if (personBo.getSalary()>1000000){
        // return Result.error(ResultVO.SALARY_ERROR);
        // }
        if (StrUtil.isBlank(person.getName())) {
            return Result.error(ResultVO.PARAM_EMPTY);
        }
        if (person.getSex() != 1 && person.getSex() != 2) {
            return Result.error(ResultVO.SEX_ERROR);
        }
        return Result.success("ok");
    }

    /**
     * 申请社保转移
     * 
     * @param apply
     * @return
     */
    @Override
    public Result<String> applyForTransfer(Apply apply) {

        if (StrUtil.isEmpty(apply.getApplicant()) || StrUtil.isEmpty(apply.getCurrentBureauAddress())
                || StrUtil.isEmpty(apply.getToBureauAddress())) {
            return Result.error(ResultVO.PARAM_EMPTY);
        }
        List<String> funcParam = new ArrayList<>();
        funcParam.add(apply.getFromCity());
        funcParam.add(apply.getToCity());
        // 申请人
        funcParam.add(apply.getApplicant());
        funcParam.add(apply.getCurrentBureauAddress());
        funcParam.add(apply.getToBureauAddress());

        String _result = weBASEUtils.funcPost(ownerAddress, APPLY_FOR_TRANSFER, funcParam);
        JSONObject obj = JSONUtil.parseObj(_result);
        String statusOK = obj.get("message").toString();
        return statusOK.equals(EnumConstant.STATUS_OK) ? Result.success(EnumConstant.STATUS_OK)
                : Result.error(ResultVO.CONTRACT_ERROR);

    }

    /**
     * 社保缴费
     * 
     * @param insuranceAccountBo
     * @return
     */
    @Override
    public Result<String> makePayment(InsuranceAccount insuranceAccountBo) {

        if (StrUtil.isEmpty(insuranceAccountBo.getAddress())) {
            return Result.error(ResultVO.PARAM_EMPTY);
        }
        try {
            // 获取所有的雇主账户地址
            String sponsorResult = weBASEUtils.funcPost(ownerAddress, GET_SPONSORS_LIST, new ArrayList());
            JSONArray sponsorResultJson = JSONUtil.parseArray(sponsorResult);
            if (sponsorResultJson.isEmpty()) {
                return Result.error(ResultVO.COMPANY_NOT_EXIST);// 提前返回，防止空指针异常
            }
            String sponsorAddressString = sponsorResultJson.get(0).toString();
            JSONArray sponsorAddressArray = JSONUtil.parseArray(sponsorAddressString);
            // 根据传入的用户地址查询对应的雇主名字和雇主地址
            String sponsorName = "";
            String sponsorAddress = "";
            for (Object address : sponsorAddressArray) {
                if (!(address instanceof String)) {
                    continue;
                }
                // 通过方法获取到该地址的账号详细信息
                com.example.model.vo.InsuranceAccount insuranceAccount = getInsuranceAccountDetail((String) address,
                        (String) address);
                sponsorAddress = insuranceAccount.getSponsorAddress();
                if (sponsorAddress != null && !sponsorAddress.equals(address)) {
                    sponsorName = insuranceAccount.getSponsorName();
                    break;// 找到立马跳出循环
                }
            }
            // 如果sponsorName等于空，或者 sponsorName不等于传进来中的sponsorName，则返回错误
            if (StrUtil.isEmpty(sponsorName) || !sponsorName.equals(insuranceAccountBo.getSponsorName())) {
                return Result.error(ResultVO.COMPANY_NOT_EXIST);
            }

            List<Object> funcParam = new ArrayList<>();
            funcParam.add(insuranceAccountBo.getAddress());
            funcParam.add(insuranceAccountBo.getSalary());
            funcParam.add(sponsorAddress);

            String _result = weBASEUtils.funcPost(ownerAddress, MAKE_PAYMENT, funcParam);
            JSONObject obj = JSONUtil.parseObj(_result);
            String statusOK = obj.get("message").toString();

            return statusOK.equals(EnumConstant.STATUS_OK) ? Result.success(EnumConstant.STATUS_OK)
                    : Result.error(ResultVO.CONTRACT_ERROR);
        } catch (Exception e) {
            // 可以根据实际需要记录日志或处理异常
            return Result.error("An error occurred during the payment process.");
        }
    }

    /**
     * 获取社保账户详细
     * 
     * @param userAddress
     * @param accountAddress
     * @return
     */
    public com.example.model.vo.InsuranceAccount getInsuranceAccountDetail(String userAddress, String accountAddress) {
        List funcParam = new ArrayList();
        funcParam.add(accountAddress);

        com.example.model.vo.InsuranceAccount insuranceAccount = new com.example.model.vo.InsuranceAccount();
        try {
            String _result = weBASEUtils.funcPost(ownerAddress, GET_INSURANCE_ACCOUNT, funcParam);
            JSONArray employeeArray = JSONUtil.parseArray(_result);
            String _result2 = weBASEUtils.funcPost(ownerAddress, GET_SPONSOR, funcParam);
            JSONArray sponsor = JSONUtil.parseArray(_result2);
            // 封装员工信息
            insuranceAccount.setPersonalBalance(Integer.parseInt(employeeArray.get(0).toString()));
            System.out.println(employeeArray.get(0).toString());
            insuranceAccount.setOverallBalance(Integer.parseInt(employeeArray.get(1).toString()));
            insuranceAccount.setSponsor(Boolean.parseBoolean(employeeArray.get(2).toString()));
            insuranceAccount.setPaymentTimestamp(Long.valueOf(employeeArray.get(3).toString()));
            insuranceAccount.setSponsorName(sponsor.get(0).toString());
            insuranceAccount.setSponsorAddress(accountAddress);

        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
        return insuranceAccount;
    }

    /**
     * 获取当前登录用户的脱敏信息
     * 对敏感信息如身份证号、联系电话、电子邮箱和钱包地址进行脱敏处理
     * 
     * @return 脱敏后的用户信息
     */
    @Override
    public Result<MaskedUserDTO> getCurrentUserMaskedInfo() {
        try {
            // int loginId = (int) StpUtil.getLoginId();
            Object o = StpUtil.getSession().get("userId");
            log.info("获取当前登录用户信息：o={}", o);
            long loginId = (long) StpUtil.getSession().get("userId");
            if (loginId == 0) {
                log.error("获取当前登录用户信息失败：用户未登录");
                return Result.error(ResultVO.UNAUTHORIZED);
            }
            Person person = userMapper.selectById(loginId);

            if (Objects.isNull(person)) {
                log.error("获取当前登录用户信息失败：用户未登录");
                return Result.error(ResultVO.UNAUTHORIZED);
            }

            // 创建脱敏后的用户DTO对象
            MaskedUserDTO maskedUserDTO = new MaskedUserDTO();

            // 复制基本信息（非敏感信息）
            BeanUtil.copyProperties(person, maskedUserDTO);

            // 对敏感信息进行脱敏处理
            maskedUserDTO.setMaskedIdNumber(MaskingUtils.maskIdNumber(person.getIdNumber()));
            maskedUserDTO.setMaskedPhone(MaskingUtils.maskPhone(person.getPhone()));
            maskedUserDTO.setMaskedEmail(MaskingUtils.maskEmail(person.getEmail()));
            maskedUserDTO.setMaskedEmployeeAddress(MaskingUtils.maskWalletAddress(person.getEmployeeAddress()));

            // 不返回密码信息
            // 密码信息在当前模型中不存在，所以不需要特别处理

            log.info("成功获取用户脱敏信息: {}", maskedUserDTO.getName());
            return Result.success(maskedUserDTO);

        } catch (Exception e) {
            log.error("获取当前登录用户脱敏信息时发生异常", e);
            return Result.error(ResultVO.INTERNAL_ERROR);
        }
    }

    /**
     * 计算退休金
     * 
     * @param calculateRetirementBo
     * @return
     */
    @Override
    public Result<Double> calculateRetirementPension(CaculateRetirement calculateRetirementBo) {
        String userAddress = calculateRetirementBo.getUserAddress();
        List<Object> funcParams = new ArrayList<>();
        funcParams.add(calculateRetirementBo.getUserAddress());
        String result = weBASEUtils.funcPost(userAddress, "getPersonInfoAndAccount", funcParams);
        JSONArray personInfoAndAccount = JSONUtil.parseArray(result);

        int currentAge = Integer.parseInt(personInfoAndAccount.get(0).toString()); // 获取当前年龄
        int currentSalary = Integer.parseInt(personInfoAndAccount.get(1).toString()); // 获取当前工资
        if (currentAge == 0 || currentSalary == 0) {
            // 返回错误
            return Result.error(ResultVO.PARAM_ERROR);
        }

        // 计算缴费年限
        int contributionYears = calculateRetirementBo.getRetirementAge() - currentAge;

        // 假设个人工资增长率为5%，职工工资增长率为3%
        double personalGrowthRate = 0.05;
        double staffGrowthRate = 0.03;

        // 计算退休时的个人月平均工资
        double indexedAverageSalary = currentSalary;
        for (int i = 0; i < contributionYears; i++) {
            indexedAverageSalary *= (1 + personalGrowthRate);
        }

        // 计算退休时全省上年度在岗职工月平均工资
        double indexedAverageStaffSalary = calculateRetirementBo.getAverageSalary();
        for (int i = 0; i < contributionYears; i++) {
            indexedAverageStaffSalary *= (1 + staffGrowthRate);
        }

        // 计算基础养老金 P1
        double P1 = (indexedAverageStaffSalary + indexedAverageSalary) / 2 * contributionYears * 0.01;

        // 计算个人账户养老金 P2
        double accumulatedFunds = Double.parseDouble(personInfoAndAccount.get(2).toString());
        double P2 = accumulatedFunds / contributionYears;

        // 过渡性养老金 P3 按1.3%取值，这里简化计算，实际应考虑更多因素
        double P3 = indexedAverageSalary * contributionYears * 0.013;

        // 计算总退休金 P
        double totalRetirementPension = P1 + P2 + P3;

        return Result.success(totalRetirementPension);
    }

    /**
     * 更新用户头像
     * 上传头像到阿里云OSS并更新用户头像URL
     *
     * @param file 头像文件
     * @return 更新结果，包含头像URL
     */
    @Override
    public Result<String> updateAvatar(MultipartFile file) {
        try {
            // 获取当前登录用户ID
            Long userId = StpUtil.getLoginIdAsLong();
            log.info("更新用户头像，用户ID: {}", userId);

            // 上传头像到阿里云OSS
            String avatarUrl = aliOSSUtils.upload(file);
            log.info("头像上传成功，URL: {}", avatarUrl);

            // 更新用户头像URL
            Person person = new Person();
            person.setId(userId);
            person.setAvatar(avatarUrl);
            person.setUpdateTime(LocalDateTime.now());

            // 使用MyBatis-Plus的updateById方法更新用户信息
            int result = userMapper.updateById(person);

            if (result > 0) {
                log.info("用户头像更新成功，用户ID: {}", userId);
                return Result.success(avatarUrl);
            } else {
                log.error("用户头像更新失败，用户ID: {}", userId);
                return Result.error("头像更新失败");
            }
        } catch (Exception e) {
            log.error("更新头像过程中发生异常", e);
            return Result.error("头像更新异常: " + e.getMessage());
        }
    }

    @Override
    public Result<String> updatePhone(UpdatePhoneDTO updatePhoneDTO) {
        return null;
    }

    /**
     * 修改用户手机号
     * 验证并更新当前登录用户的手机号
     *
     * @param oldPhone 旧手机号
     * @return 更新结果
     */
    @Override
    public Result<String> verifyOldPhone(String oldPhone) {
        try {
            Long userId = StpUtil.getLoginIdAsLong();
            log.info("验证用户原手机号，用户ID: {}", userId);

            if (StrUtil.isEmpty(oldPhone)) {
                log.warn("原手机号参数为空");
                return Result.error(ResultVO.PARAM_EMPTY);
            }

            Person currentUser = userMapper.selectById(userId);
            if (currentUser == null) {
                log.error("用户不存在，用户ID: {}", userId);
                return Result.error(ResultVO.ACCOUNTS_NOT_EXIST);
            }

            if (!oldPhone.equals(currentUser.getPhone())) {
                log.warn("原手机号不匹配，用户ID: {}, 输入手机号: {}, 实际手机号: {}",
                        userId, oldPhone, currentUser.getPhone());
                return Result.error(ResultVO.PARAM_ERROR, "原手机号不正确");
            }

            return Result.success("原手机号验证成功");
        } catch (Exception e) {
            log.error("验证原手机号过程中发生异常", e);
            return Result.error("验证原手机号异常: " + e.getMessage());
        }
    }

    @Override
    public Result<String> updatePhone(String newPhone) {
        try {
            Long userId = StpUtil.getLoginIdAsLong();
            log.info("更新用户手机号，用户ID: {}", userId);

            if (StrUtil.isEmpty(newPhone)) {
                log.warn("新手机号参数为空");
                return Result.error(ResultVO.PARAM_EMPTY);
            }

            if (!PhoneValidator.isValidPhone(newPhone)) {
                log.warn("新手机号格式不正确: {}", newPhone);
                return Result.error(ResultVO.PARAM_ERROR, "手机号格式不正确");
            }

            Person existingPerson = userMapper.getPersonByPhone(newPhone);
            if (existingPerson != null && !existingPerson.getId().equals(userId)) {
                log.warn("手机号已被使用: {}", newPhone);
                return Result.error(ResultVO.QUERY_EXISTS, "该手机号已被其他用户使用");
            }

            Person person = new Person();
            person.setId(userId);
            person.setPhone(newPhone);
            person.setUpdateTime(LocalDateTime.now());

            int result = userMapper.updateById(person);

            if (result > 0) {
                log.info("用户手机号更新成功，用户ID: {}, 新手机号: {}", userId, newPhone);
                return Result.success("手机号更新成功");
            } else {
                log.error("用户手机号更新失败，用户ID: {}", userId);
                return Result.error("手机号更新失败");
            }
        } catch (Exception e) {
            log.error("更新手机号过程中发生异常", e);
            return Result.error("更新手机号异常: " + e.getMessage());
        }
    }

    @Override
    public UserProfile getProfile(String userAddress) {
        StpUtil.checkLogin();
        Result<MaskedUserDTO> currentUserMaskedInfo = getCurrentUserMaskedInfo();
        MaskedUserDTO userInfo = currentUserMaskedInfo.getData();
        UserProfile userProfile = new UserProfile();
        userProfile.setUserAddress(userAddress);
        userProfile.setName(userInfo.getName());
        userProfile.setMaskedId(userInfo.getMaskedIdNumber());
        userProfile.setAge(userInfo.getAge());
        userProfile.setPhone(userInfo.getMaskedPhone());
        userProfile.setLocation(userInfo.getAddress());
        userProfile.setInsuranceYears(userInfo.getWorkYears());
        userProfile.setStatus(userInfo.getStatus());
        return userProfile;
    }

    @Override
    public List<String> getActiveUsers() {
        log.info("开始获取最近活跃用户列表");
        if (Boolean.TRUE.equals(redisTemplate.hasKey(RedisConstant.USER_ACTIVE))) {
            return redisTemplate.opsForList().range(RedisConstant.USER_ACTIVE, 0, -1);
        }

        // 计算30天前的日期
        Date thirtyDaysAgo = new Date(System.currentTimeMillis() - 30 * 24 * 60 * 60 * 1000L);

        // 查询最近30天内有登录记录的用户
        List<String> activeLoginUsers = loginLogMapper.selectList(
                new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<LoginLog>()
                        .gt(LoginLog::getLoginTime, thirtyDaysAgo)
                        .select(LoginLog::getUserAddress))
                .stream().map(LoginLog::getUserAddress).distinct().collect(java.util.stream.Collectors.toList());

        // 查询最近30天内有操作记录的用户
        List<String> activeOperationUsers = operationLogMapper.selectList(
                new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<OperationLog>()
                        .gt(OperationLog::getOperationTime, thirtyDaysAgo)
                        .select(OperationLog::getUserAddress))
                .stream().map(OperationLog::getUserAddress).distinct().collect(java.util.stream.Collectors.toList());

        // 合并两个列表并去重
        java.util.Set<String> activeUserSet = new java.util.HashSet<>();
        activeUserSet.addAll(activeLoginUsers);
        activeUserSet.addAll(activeOperationUsers);

        List<String> result = new java.util.ArrayList<>(activeUserSet);
        log.info("获取到{}个活跃用户", result.size());

        // 加入缓存，并设置过期时间为1小时
        redisTemplate.opsForList().rightPushAll(RedisConstant.USER_ACTIVE, result);
        redisTemplate.expire(RedisConstant.USER_ACTIVE, 1, TimeUnit.HOURS);
        return result;
    }

    @Override
    public boolean requireReVerification(String userAddress) {
        // 1. 获取被重新验证的用户信息
        Person person = userMapper.getPersonByAddress(userAddress);
        if (person == null) {
            return false;
        }
        // 把该用户强制注销
        StpUtil.logout(person.getId());
        // 4.不在线，则返回true，并让用户重新验证
        return true;
    }

    @Override
    public boolean markAsRisky(String userAddress) {
        log.info("将用户标记为有风险，用户地址：{}", userAddress);
        try {
            Person person = userMapper.getPersonByAddress(userAddress);
            if (person == null) {
                log.error("用户不存在，用户地址：{}", userAddress);
                return false;
            }

            // 更新用户风险等级为中风险
            return updateUserRiskLevel(userAddress, 1);
        } catch (Exception e) {
            log.error("标记用户风险状态时发生异常", e);
            return false;
        }
    }

    @Override
    public boolean limitSensitiveOperations(String userAddress) {
        log.info("限制用户敏感操作，用户地址：{}", userAddress);
        try {
            Person person = userMapper.getPersonByAddress(userAddress);
            if (person == null) {
                log.error("用户不存在，用户地址：{}", userAddress);
                return false;
            }

            // 限制用户敏感操作，例如大额交易
            StpUtil.disable(person.getId(), "sensitive_operations", 86400);
            banUser(person.getId(), LocalDateTime.now().plusDays(1), 2);
            log.info("已限制用户敏感操作，用户地址：{}", userAddress);
            return true;
        } catch (Exception e) {
            log.error("限制用户敏感操作时发生异常", e);
            return false;
        }
    }

    @Override
    public boolean updateUserRiskLevel(String userAddress, Integer riskLevel) {
        log.info("更新用户风险等级，用户地址：{}，风险等级：{}", userAddress, riskLevel);
        try {
            Person person = userMapper.getPersonByAddress(userAddress);
            if (person == null) {
                log.error("用户不存在，用户地址：{}", userAddress);
                return false;
            }

            // 更新用户风险等级
            Person updatePerson = new Person();
            updatePerson.setId(person.getId());
            updatePerson.setRiskLevel(riskLevel);
            updatePerson.setUpdateTime(LocalDateTime.now());

            int result = userMapper.updateById(updatePerson);
            if (result > 0) {
                log.info("用户风险等级更新成功，用户地址：{}，风险等级：{}", userAddress, riskLevel);
                return true;
            } else {
                log.error("用户风险等级更新失败，用户地址：{}", userAddress);
                return false;
            }
        } catch (Exception e) {
            log.error("更新用户风险等级时发生异常", e);
            return false;
        }
    }

}
